package com.xzixi.websocket.interceptablewebsocketdemo.controller;

import com.xzixi.websocket.interceptablewebsocketdemo.entity.Resource;
import com.xzixi.websocket.interceptablewebsocketdemo.entity.User;
import com.xzixi.websocket.interceptablewebsocketdemo.service.ResourceService;
import com.xzixi.websocket.interceptablewebsocketdemo.util.GenericMessageBuilder;
import com.xzixi.websocket.interceptablewebsocketdemo.util.MessageHeadersBuilder;
import com.xzixi.websocket.interceptablewebsocketdemo.websocket.SessionIdRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author 薛凌康
 */
@Controller
public class MainController {

    @Autowired
    private ResourceService resourceService;
    @Autowired
    private SessionIdRegistry sessionIdRegistry;
    @Autowired
    private SimpMessagingTemplate template;

    @GetMapping({"/", "login"})
    public String toLogin() {
        return "login";
    }

    @GetMapping("index")
    public String toIndex() {
        return "index";
    }

    @PostMapping("login")
    @ResponseBody
    public String login(User user, HttpSession session) {
        String username = user.getUsername();
        String password = user.getPassword();
        if (("admin".equals(username) && "admin".equals(password))
                || ("guest".equals(username) && "guest".equals(password))
                || ("user".equals(username) && "user".equals(password))) {
            // 查询权限
            List<Resource> resources = resourceService.findResourceByUsername(username);
            user.setResources(resources);
            session.setAttribute("user", user);
            return "ok";
        }
        return "error";
    }

    @PostMapping("checkLogin")
    @ResponseBody
    public String checkLogin(HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user==null) {
            return "error";
        }
        return "ok";
    }

    @PostMapping("logout")
    @ResponseBody
    public String logout(HttpSession session) {
        session.removeAttribute("user");
        return "ok";
    }

    /**
     * 发送消息可以用@MessageMapping，
     * 我习惯用@RequestMapping，这样可以用到全局异常拦截
     */
    @PostMapping("broadcast")
    @ResponseBody
    public String broadcast(String content, HttpSession session) {
        User user = (User) session.getAttribute("user");
        String username = user.getUsername();
        // 只有admin用户可以发送广播，案例只做简单判断，正常开发时使用权限验证
        if (!"admin".equals(username)) {
            return "error";
        }
        // 用map包装广播消息
        Map<String, String> map = new HashMap<>();
        map.put("username", username);
        map.put("content", content);
        GenericMessage message = new GenericMessageBuilder()
                .payload(map)
                .destination("/topic/broadcast")
                .leaveMutable(true)
                .build();
        template.send(message);
        return "ok";
    }

    /**
     * 发送消息可以用@MessageMapping，
     * 我习惯用@RequestMapping，这样可以用到全局异常拦截
     */
    @PostMapping("chat")
    @ResponseBody
    public String chat(String target, String content, HttpSession session) {
        User user = (User) session.getAttribute("user");
        String username = user.getUsername();
        // 只有admin和user可以发送聊天消息，案例只做简单判断，正常开发时使用权限验证
        if (!"admin".equals(username) && !"user".equals(username)) {
            return "error";
        }
        // 查询目标用户的sessionId
        Set<String> sessionIds = sessionIdRegistry.getSessionIds(target);
        // 用map包装聊天消息
        Map<String, String> map = new HashMap<>();
        map.put("username", username);
        map.put("content", content);
        sessionIds.forEach(sessionId -> template.convertAndSendToUser(
                sessionId,
                "/topic/chat",
                map,
                new MessageHeadersBuilder()
                        .sessionId(sessionId)
                        .leaveMutable(true)
                        .build()
        ));
        return "ok";
    }

}
